﻿#include "TextWidgetPipeline.h"
#include "Render/VulkanContext.h"
#include "Render/Material/VulkanShaders.h"
#include "Render/Material/VulkanShader.h"

void STextWidgetPipeline::Init()
{
    CreateTextImageSampler();
    CreateStaticPipeline();
    CreateDynamicPipeline();
}

void STextWidgetPipeline::CreateTextImageSampler()
{
    //create text image sampler
    vk::SamplerCreateInfo SamplerCreateInfo=vk::SamplerCreateInfo()
        .setMagFilter(vk::Filter::eLinear)
        .setMinFilter(vk::Filter::eLinear)
        .setAddressModeU(vk::SamplerAddressMode::eClampToEdge)
        .setAddressModeV(vk::SamplerAddressMode::eClampToEdge)
        .setAddressModeW(vk::SamplerAddressMode::eClampToEdge)
        .setAnisotropyEnable(false)
        .setMaxAnisotropy(1)
        .setBorderColor(vk::BorderColor::eFloatOpaqueWhite)
        .setUnnormalizedCoordinates(false)
        .setCompareEnable(false)
        .setCompareOp(vk::CompareOp::eAlways)
        .setMipmapMode(vk::SamplerMipmapMode::eLinear)
        .setMipLodBias(0.0f)
        .setMinLod(0.0f)
        .setMaxLod(0.0f);

    TextImageSampler=CVulkanContext::Get()->GetDevice().createSampler(SamplerCreateInfo);
}

void STextWidgetPipeline::CreateStaticPipeline()
{
    //创建描述符布局
    //描述符binding 0 为 一组纹理,
    //binding 1 为 一个uniforbuffer,
    TVector<vk::DescriptorSetLayoutBinding> DescriptorSetLayoutBindings=
    {
        vk::DescriptorSetLayoutBinding()
            .setBinding(0)
            .setDescriptorType(vk::DescriptorType::eCombinedImageSampler)
            .setDescriptorCount(1)
            .setStageFlags(vk::ShaderStageFlagBits::eFragment)
        ,
        vk::DescriptorSetLayoutBinding()
            .setBinding(1)
            .setDescriptorType(vk::DescriptorType::eUniformBuffer)
            .setDescriptorCount(1)
            .setStageFlags(vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eVertex)
    };
    
    vk::DescriptorSetLayoutCreateInfo DescriptorSetLayoutCreateInfo = vk::DescriptorSetLayoutCreateInfo()
        .setBindings(DescriptorSetLayoutBindings);


    StaticDescriptorSetLayout.Layout =CVulkanContext::Get()->GetDevice().createDescriptorSetLayout(DescriptorSetLayoutCreateInfo);
    StaticDescriptorSetLayout.DescriptorNums.CombinedImageSamplerDescriptorNum= 1;
    StaticDescriptorSetLayout.DescriptorNums.UniformBufferDescriptorNum= 1;

    TVector<vk::PushConstantRange> PushConstantRanges=
    {
        vk::PushConstantRange()
        .setStageFlags(vk::ShaderStageFlagBits::eVertex)
        .setOffset(0)
        .setSize(sizeof(STextWidgetPipeline::SStaticTextPushConstant))
    };

    vk::PipelineLayoutCreateInfo PipelineLayoutCreateInfo = vk::PipelineLayoutCreateInfo()
        .setSetLayouts(StaticDescriptorSetLayout.Layout)
        .setPushConstantRanges(PushConstantRanges);

    StaticPipelineLayout =CVulkanContext::Get()->GetDevice().createPipelineLayout(PipelineLayoutCreateInfo);

    //create pipeline
    auto VertexShader= CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"StaticTextWidget_vert");
    auto FragmentShader= CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"StaticTextWidget_frag");

    //dynamic state
    vk::DynamicState DynamicState[2]={vk::DynamicState::eViewport,vk::DynamicState::eScissor};

    vk::PipelineDynamicStateCreateInfo PipelineDynamicStateCreateInfo=vk::PipelineDynamicStateCreateInfo()
        .setDynamicStateCount(2)
        .setPDynamicStates(DynamicState);

    vk::PipelineShaderStageCreateInfo PipelineShaderStageCreateInfo[2];
    PipelineShaderStageCreateInfo[0]=vk::PipelineShaderStageCreateInfo()
        .setStage(vk::ShaderStageFlagBits::eVertex)
        .setModule(VertexShader->Module)
        .setPName("main");

    PipelineShaderStageCreateInfo[1]=vk::PipelineShaderStageCreateInfo()
        .setStage(vk::ShaderStageFlagBits::eFragment)
        .setModule(FragmentShader->Module)
        .setPName("main");

    vk::PipelineVertexInputStateCreateInfo PipelineVertexInputStateCreateInfo=vk::PipelineVertexInputStateCreateInfo()
        .setVertexBindingDescriptionCount(0)
        .setVertexAttributeDescriptionCount(0);

    vk::PipelineInputAssemblyStateCreateInfo PipelineInputAssemblyStateCreateInfo=vk::PipelineInputAssemblyStateCreateInfo()
        .setTopology(vk::PrimitiveTopology::eTriangleStrip);

    vk::PipelineViewportStateCreateInfo PipelineViewportStateCreateInfo=vk::PipelineViewportStateCreateInfo()
        .setViewportCount(1)
        .setScissorCount(1);

    vk::PipelineRasterizationStateCreateInfo PipelineRasterizationStateCreateInfo=vk::PipelineRasterizationStateCreateInfo()
        .setPolygonMode(vk::PolygonMode::eFill)
        .setCullMode(vk::CullModeFlagBits::eNone)
        .setFrontFace(vk::FrontFace::eClockwise)
        .setLineWidth(1.0f);

    vk::PipelineMultisampleStateCreateInfo PipelineMultisampleStateCreateInfo=vk::PipelineMultisampleStateCreateInfo()
        .setRasterizationSamples(vk::SampleCountFlagBits::e1);

    vk::PipelineDepthStencilStateCreateInfo PipelineDepthStencilStateCreateInfo=vk::PipelineDepthStencilStateCreateInfo()
        .setDepthTestEnable(true)
        .setDepthWriteEnable(true)
        .setDepthCompareOp(vk::CompareOp::eLessOrEqual)
        .setDepthBoundsTestEnable(false)
        .setStencilTestEnable(false);

    vk::PipelineColorBlendAttachmentState PipelineColorBlendAttachmentState=vk::PipelineColorBlendAttachmentState()
    
            .setColorWriteMask(
                vk::ColorComponentFlagBits::eR
                |vk::ColorComponentFlagBits::eG
                |vk::ColorComponentFlagBits::eB
                |vk::ColorComponentFlagBits::eA
            )
            .setBlendEnable(true) //text color is transparent
            .setSrcColorBlendFactor(vk::BlendFactor::eSrcAlpha) //text color
            .setDstColorBlendFactor(vk::BlendFactor::eOneMinusSrcAlpha) //background color
            .setColorBlendOp(vk::BlendOp::eAdd)
            .setSrcAlphaBlendFactor(vk::BlendFactor::eZero)
            .setDstAlphaBlendFactor(vk::BlendFactor::eOne)
            .setAlphaBlendOp(vk::BlendOp::eAdd)
            ;   

    vk::PipelineColorBlendStateCreateInfo PipelineColorBlendStateCreateInfo=vk::PipelineColorBlendStateCreateInfo()
        .setAttachmentCount(1)
        .setPAttachments(&PipelineColorBlendAttachmentState);

    vk::GraphicsPipelineCreateInfo GraphicsPipelineCreateInfo=vk::GraphicsPipelineCreateInfo()
        .setPDynamicState(&PipelineDynamicStateCreateInfo)
        .setStageCount(2)
        .setPStages(PipelineShaderStageCreateInfo)
        .setPVertexInputState(&PipelineVertexInputStateCreateInfo)
        .setPInputAssemblyState(&PipelineInputAssemblyStateCreateInfo)
        .setPViewportState(&PipelineViewportStateCreateInfo)
        .setPRasterizationState(&PipelineRasterizationStateCreateInfo)
        .setPMultisampleState(&PipelineMultisampleStateCreateInfo)
        .setPDepthStencilState(&PipelineDepthStencilStateCreateInfo)
        .setPColorBlendState(&PipelineColorBlendStateCreateInfo)
        .setLayout(StaticPipelineLayout)
        .setRenderPass(CVulkanContext::Get()->GetWidgetRenderPass())
        .setSubpass(0);

    StaticPipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;

}

void STextWidgetPipeline::CreateDynamicPipeline()
{
    //创建描述符布局
    //描述符binding 0 为 一组纹理,
    //binding 1 为 一个uniforbuffer,
    TVector<vk::DescriptorSetLayoutBinding> DescriptorSetLayoutBindings=
    {
        vk::DescriptorSetLayoutBinding()
            .setBinding(0)
            .setDescriptorType(vk::DescriptorType::eCombinedImageSampler)
            .setDescriptorCount(1)
            .setStageFlags(vk::ShaderStageFlagBits::eFragment)
        ,
        vk::DescriptorSetLayoutBinding()
            .setBinding(1)
            .setDescriptorType(vk::DescriptorType::eUniformBuffer)
            .setDescriptorCount(1)
            .setStageFlags(vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eVertex)
    };
    
    vk::DescriptorSetLayoutCreateInfo DescriptorSetLayoutCreateInfo = vk::DescriptorSetLayoutCreateInfo()
        .setBindings(DescriptorSetLayoutBindings);


    DynamicDescriptorSetLayout.Layout =CVulkanContext::Get()->GetDevice().createDescriptorSetLayout(DescriptorSetLayoutCreateInfo);
    DynamicDescriptorSetLayout.DescriptorNums.CombinedImageSamplerDescriptorNum= 1;
    DynamicDescriptorSetLayout.DescriptorNums.UniformBufferDescriptorNum=1;

    TVector<vk::PushConstantRange> PushConstantRanges=
    {
        vk::PushConstantRange()
        .setStageFlags(vk::ShaderStageFlagBits::eVertex)
        .setOffset(0)
        .setSize(sizeof(SDynamicTextPushConstant))
    };

    vk::PipelineLayoutCreateInfo PipelineLayoutCreateInfo = vk::PipelineLayoutCreateInfo()
        .setSetLayouts(DynamicDescriptorSetLayout.Layout)
        .setPushConstantRanges(PushConstantRanges);

    DynamicPipelineLayout =CVulkanContext::Get()->GetDevice().createPipelineLayout(PipelineLayoutCreateInfo);

    //create pipeline
    auto VertexShader= CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"TextWidget_vert");
    auto FragmentShader= CVulkanContext::Get()->GetShaderManager()->GetVulkanOnlyShader(U"TextWidget_frag");

    //dynamic state
    vk::DynamicState DynamicState[2]={vk::DynamicState::eViewport,vk::DynamicState::eScissor};

    vk::PipelineDynamicStateCreateInfo PipelineDynamicStateCreateInfo=vk::PipelineDynamicStateCreateInfo()
        .setDynamicStateCount(2)
        .setPDynamicStates(DynamicState);

    vk::PipelineShaderStageCreateInfo PipelineShaderStageCreateInfo[2];
    PipelineShaderStageCreateInfo[0]=vk::PipelineShaderStageCreateInfo()
        .setStage(vk::ShaderStageFlagBits::eVertex)
        .setModule(VertexShader->Module)
        .setPName("main");

    PipelineShaderStageCreateInfo[1]=vk::PipelineShaderStageCreateInfo()
        .setStage(vk::ShaderStageFlagBits::eFragment)
        .setModule(FragmentShader->Module)
        .setPName("main");

    vk::PipelineVertexInputStateCreateInfo PipelineVertexInputStateCreateInfo=vk::PipelineVertexInputStateCreateInfo()
        .setVertexBindingDescriptionCount(0)
        .setVertexAttributeDescriptionCount(0);

    vk::PipelineInputAssemblyStateCreateInfo PipelineInputAssemblyStateCreateInfo=vk::PipelineInputAssemblyStateCreateInfo()
        .setTopology(vk::PrimitiveTopology::eTriangleStrip);

    vk::PipelineViewportStateCreateInfo PipelineViewportStateCreateInfo=vk::PipelineViewportStateCreateInfo()
        .setViewportCount(1)
        .setScissorCount(1);

    vk::PipelineRasterizationStateCreateInfo PipelineRasterizationStateCreateInfo=vk::PipelineRasterizationStateCreateInfo()
        .setPolygonMode(vk::PolygonMode::eFill)
        .setCullMode(vk::CullModeFlagBits::eNone)
        .setFrontFace(vk::FrontFace::eClockwise)
        .setLineWidth(1.0f);

    vk::PipelineMultisampleStateCreateInfo PipelineMultisampleStateCreateInfo=vk::PipelineMultisampleStateCreateInfo()
        .setRasterizationSamples(vk::SampleCountFlagBits::e1);

    vk::PipelineDepthStencilStateCreateInfo PipelineDepthStencilStateCreateInfo=vk::PipelineDepthStencilStateCreateInfo()
        .setDepthTestEnable(true)
        .setDepthWriteEnable(true)
        .setDepthCompareOp(vk::CompareOp::eLessOrEqual)
        .setDepthBoundsTestEnable(false)
        .setStencilTestEnable(false);

    vk::PipelineColorBlendAttachmentState PipelineColorBlendAttachmentState=vk::PipelineColorBlendAttachmentState()
    
            .setColorWriteMask(
                vk::ColorComponentFlagBits::eR
                |vk::ColorComponentFlagBits::eG
                |vk::ColorComponentFlagBits::eB
                |vk::ColorComponentFlagBits::eA
            )
            .setBlendEnable(true) //text color is transparent
            .setSrcColorBlendFactor(vk::BlendFactor::eSrcAlpha) //text color
            .setDstColorBlendFactor(vk::BlendFactor::eOneMinusSrcAlpha) //background color
            .setColorBlendOp(vk::BlendOp::eAdd)
            .setSrcAlphaBlendFactor(vk::BlendFactor::eZero)
            .setDstAlphaBlendFactor(vk::BlendFactor::eOne)
            .setAlphaBlendOp(vk::BlendOp::eAdd)
            ;   

    vk::PipelineColorBlendStateCreateInfo PipelineColorBlendStateCreateInfo=vk::PipelineColorBlendStateCreateInfo()
        .setAttachmentCount(1)
        .setPAttachments(&PipelineColorBlendAttachmentState);

    vk::GraphicsPipelineCreateInfo GraphicsPipelineCreateInfo=vk::GraphicsPipelineCreateInfo()
        .setPDynamicState(&PipelineDynamicStateCreateInfo)
        .setStageCount(2)
        .setPStages(PipelineShaderStageCreateInfo)
        .setPVertexInputState(&PipelineVertexInputStateCreateInfo)
        .setPInputAssemblyState(&PipelineInputAssemblyStateCreateInfo)
        .setPViewportState(&PipelineViewportStateCreateInfo)
        .setPRasterizationState(&PipelineRasterizationStateCreateInfo)
        .setPMultisampleState(&PipelineMultisampleStateCreateInfo)
        .setPDepthStencilState(&PipelineDepthStencilStateCreateInfo)
        .setPColorBlendState(&PipelineColorBlendStateCreateInfo)
        .setLayout(DynamicPipelineLayout)
        .setRenderPass(CVulkanContext::Get()->GetWidgetRenderPass())
        .setSubpass(0);

    DynamicPipeline=CVulkanContext::Get()->GetDevice().createGraphicsPipeline(nullptr,GraphicsPipelineCreateInfo).value;


}
